fix(objectql): enforce per-option visibleWhen on checkboxes + string-match option values (objectui#2729)#3350
Merged
Conversation
…ption values by string (objectui#2729) Server-side per-option gating covered select/multiselect/radio but two holes let gated values through on write: - checkboxes was excluded from CHOICE_FIELD_TYPES, so a gated `checkboxes` option (client widget cascades like multiselect since objectui#2715) was hidden in the UI but accepted from a crafted write. Now enforced element-wise on insert/update/bulk-update like multiselect. - Option matching used strict `===` while the enum validator compares by String(...); a numeric option value sent as a string passed the enum check but missed its visibleWhen gate (fail-open). Now coerces both sides. select/multiselect/radio behavior unchanged; fail-open on unbound current_user / unevaluable predicates preserved. Adds checkboxes + coercion cases to rule-validator.option-visibility.test.ts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Jul 20, 2026
…d + Console) Continues the v16 page from the latest front/back-end code. Since the rc.0 cut, 9 backend changesets landed and the objectui pin advanced 94d4876 -> af1b0db (objectui objectstack-ai#2706-objectstack-ai#2736). Sourced from each repo's own changesets. - Retitles the now-stale 'pending the next console pin' subsection: those 4 frontend items (objectui#2701/objectstack-ai#2706/objectstack-ai#2707/objectstack-ai#2708) are now bundled as the pin advanced; points to the new running section. - Adds a 'Landed since 16.0.0-rc.0' section: - Breaking/behavior: aiStudio/aiSeat alias removal (objectstack-ai#3308); date-arithmetic now a build-time error (objectstack-ai#3306); checkboxes per-option visibleWhen + string option matching (objectstack-ai#3350). - New backend: formula null-guard/floor/ceil (objectstack-ai#3306); engine-owned managedBy bucket (ADR-0103 addendum, objectstack-ai#3343); approvals viewer gating (objectstack-ai#3344) + decision attachments (objectstack-ai#3332); discovery transactionalBatch bit (objectstack-ai#3298); action resultDialog i18n (objectstack-ai#3347); collab-notification/storage localization + wired notifications REST routes (objectstack-ai#3354). - Console (now bundled): option-widget visibleWhen parity, approvals-inbox server-viewer gating + composer retirement, related-list pagination, inline-analytics renderer retirement, authenticated api-fetch threading, result-dialog i18n, engine-owned bucket UI, write-failure surfacing. - Adds aiStudio/aiSeat and date-arithmetic to the upgrade checklist; updates the Console-section intro for the advanced pin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AHVoqyH9VAjmbyMN1Ri2jf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses objectstack-ai/objectui#2729 (server-side enforcement of role-gated / dependent option values).
Context
Server-side per-option
visibleWhenenforcement already exists (packages/objectql/src/validation/rule-validator.ts→evaluateOptionVisibility, wired into insert / single-update / bulk-update). Investigating objectui#2729 surfaced that it coveredselect/multiselect/radiobut left two holes that let gated values through on write — the exact "client hides it, server must reject it" boundary the issue is about.Fixes
checkboxeswas not enforced.CHOICE_FIELD_TYPESomittedcheckboxes, sofieldHasOptionVisibilityreturned false for it and its options were never re-evaluated. Since objectui#2735 shipped client-sidecheckboxescascading, a gatedcheckboxesoption was hidden in the UI yet accepted from a crafted write. Addedcheckboxesto the enforced set — picked values are now checked element-wise against each option'svisibleWhen(record +current_user), likemultiselect. (checkboxesis already treated as a multi-value option field by the enum validator, so this closes an inconsistency between the two validators.)Numeric option values could slip the gate. Option matching used strict
===, but the enum-membership validator (record-validator.ts) compares byString(...). A numeric option value submitted as a string (a normal REST/JSON round-trip) passed the enum check but itsvisibleWhengate found no matching option and fail-opened. Matching now coerces both sides withString(...), so the enum and visibility validators agree on which option a written value denotes.Not changed / by design
select/multiselect/radiobehavior is unchanged.current_user(system writes) or unevaluable predicates is preserved — a broken cascade predicate must never brick a write; authorization gating depends on the engine bindingcurrent_user, as before.dependsOnremains a client form-gating hint only; server enforcement keys off each option'svisibleWhen(a cascade parent is expressed inside the child's predicate, e.g.record.country == 'cn'), matching the existing design.Tests
rule-validator.option-visibility.test.ts:checkboxeselement-wise gating (+needsPriorRecord), and numeric-value coercion (both are real regression guards — they fail on the pre-fix code).src/validation/+engine.test.ts(206 passed) andplugin.integration.test.tsreal-registry path (36 passed).tsc --noEmitclean;eslint0 errors (one pre-existing unrelatedno-newwarning).🤖 Generated with Claude Code